/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.EnumConstants;

/**
 * IP地址相关工具类
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("IPs")
public class IPs implements EnumConstants
{
    public static final String IP_MIN_STR   = "0.0.0.0";
    public static final String IP_MAX_STR   = "255.255.255.255";
    public static final long IP_MIN         = 0;                //ipToLong("0.0.0.0");
    public static final long IP_MAX         = 4294967295L;      //ipToLong("255.255.255.255");
    
    /** 4节字转字符串IP */
    public static String byteToIp(byte[] value)
    {
        StringBuilder strb = new StringBuilder();
        strb.append(value[0] & 0xFF).append(".");
        strb.append(value[1] & 0xFF).append(".");
        strb.append(value[2] & 0xFF).append(".");
        strb.append(value[3] & 0xFF);
        return strb.toString();
    }
    
    /** 4节字转long型 */
    public static long byteToLong(byte[] value)
    {
        int i0 = value[0] & 0xFF;
        int i1 = value[1] & 0xFF;
        int i2 = value[2] & 0xFF;
        int i3 = value[3] & 0xFF;
        
        int ipInt = (i0 << 24) + (i1 << 16) + (i2 << 8) + i3;
        
        //转为无符号整数
        return ipInt & 0xFFFFFFFFL;
    }
    
    /** 字符串IP转long型 */
    public static long ipToLong(String ip)
    {
        int[] ints = Arrays.toIntArray(ip, "\\.");
        if (ints.length != 4)
            return -1;
        
        int ipInt = (ints[0] << 24) + (ints[1] << 16) + (ints[2] << 8) + (ints[3]);   
        long ipLong = ipInt & 0x7FFFFFFFL;
        if (ipInt < 0)
            ipLong |= 0x80000000L;
        
        return ipLong;
    }
    
    /** long型转IP格式 */
    public static String longToIp(long ip)
    {
        int[] b = new int[4];
        b[0] = (int)((ip >> 24) & 0xFF);
        b[1] = (int)((ip >> 16) & 0xFF);
        b[2] = (int)((ip >> 8) & 0xFF);
        b[3] = (int)(ip & 0xFF);
        
        return Arrays.toString(b, ".");
    }
    
    /** 把可能的255.255.003.002转化为255.255.3.2 */
    public static String trim(String ip)
    {
        int[] values = Arrays.toIntArray(ip, "\\.");
        return Arrays.toString(values, ".");
    }
    
    /** 子网掩码255.255.0.0格式转数字格式0-32，如果不是正确的掩码返回-1 */
    public static int ipMaskToInt(String ipMask)
    {
        ipMask = trim(ipMask);
        for (int i=0;i<_IP_MASK_.length;i++)
        {
            if (ipMask.equals(_IP_MASK_[i]))
                return i;
        }
        
        return -1;
    }
    
    /** 子网掩码数字格式0-32格式转IP格式255.255.0.0 */
    public static String intToIpMask(int i)
    {
        if (i > 32)
            return IP_MAX_STR;
        
        if (i < 0)
            return IP_MIN_STR;
        
        return _IP_MASK_[i];
    }
    
    /** 计算指定IP和掩码对应的允许的最大值和最小值IP */
    public static long[] calcIpMaskMinMax(String ip, int mask)
    {
        long cur = ipToLong(ip);
        long min = IP_MIN;
        long max = IP_MAX;
        
        for (int i=0;i<=32;i++)
        {
            if (mask == i)
                break;
            
            //否则向下计算
            long half = (max - min - 1) / 2 + 1;
            if (cur >= (min + half))
                min += half;
            else
                max -= half;
        }
        
        return new long[]{min, max};
    }
    
}
